<?
class TTEvent_Table_Abstract extends Zend_DB_Table_Abstract
{
	
	public $row_per_page=20;
	protected $page_info;
	protected static $data_cache=null;
	public $_not_count=false;
	public $_sequence = true;
	
	
	public function notCount(){
		$this->_not_count = true;
	}
	
	public static function getMasterDB()
	{
		return Zend_Registry::get("master_db");
	}
	
	public static function getSlaveDB($key="")
	{
		$dbAdapters=Zend_Registry::get("slave_dbs");
		if ($key!="")
		{
			return $dbAdapters[$key];
		}
		$slave_key=array_rand($dbAdapters);
		return $dbAdapters[$slave_key];
	}
	
	public function execSelectQuery($sql)
	{
		$db=$this->getSlaveDB();
		$stm=$db->query($sql);
		$data=array();
		while ($obj=$stm->fetch())
		{
			$data[]=$obj;
		}
		return $data;
	}
	
	public function execScalar($sql)
	{
		$db=$this->getSlaveDB();
		return $db->fetchOne($sql);
	}
	
	public function setRowPerPage($rowPerPage){
		$this->row_per_page = $rowPerPage;
	}
/*
* $sqlCount : if it is integer, it is total item, so do not count againt
* 
* 
* */
	public function pageQuery($sql, $args=array(), $page=0, $sqlCount = ""){
		
		if(!$this->_not_count && $this->getItemPerPage()!=-1){
			// get pager information
			$isSqlCount = false;
			$pageInfo = array();
			
			if(is_numeric($sqlCount)){
				if($sqlCount==0){
					$pageInfo['start'] = 0;
					$pageInfo['limit'] = $this->getItemPerPage();
					$pageInfo['page'] = 0;
					$pageInfo['total_item'] = 0;
					$pageInfo['total_page'] = 0;

					$ret = array();
				}
				else{
					
					$pageInfo['total_item'] = (int)$sqlCount;
					$pageInfo['total_page'] = ceil($pageInfo['total_item'] / $this->getItemPerPage());
					$pageInfo = array_merge($pageInfo, $this->pageIndex($pageInfo['total_page'], $page));
					
					$ret = $this->queryRange($sql, $args, $pageInfo['start'], $pageInfo['limit']);
				}
			}
			else{
				if($sqlCount != ""){
					$isSqlCount = true;
				}else{
					$sqlCount = $sql;
				}
				$pageInfo = $this->pageQueryInfo($sqlCount, $args,$isSqlCount);
				$pageInfo = array_merge($pageInfo, $this->pageIndex($pageInfo['total_page'], $page));
				
				$ret = $this->queryRange($sql, $args, $pageInfo['start'], $pageInfo['limit']);
			}
			
			$this->setPageInfo($pageInfo);
			return $ret;
		}
		else{
			// not for paging
			// get all row
			if($this->getItemPerPage()==-1){
				$this->getSlaveDB()->query($sql, $args)->fetchAll();
			}
			// no need count
			// get row for first page
			else{
				return $this->queryRange($sql, $args, 0, $this->getItemPerPage());
			}
			
		}
	}
	
	public function pageQuery2($sql, $args=array(), $page=0, $limit = 20){
		$page = (int)$page;
		$limit = (int)$limit;
		
		$start = $page*$limit;
		return $this->queryRange($sql, $args, $start, $limit);

	}
	
	private function queryRange($query){
		
		// configure query
		$args = func_get_args();
		$count = array_pop($args);
		$from = array_pop($args);
		array_shift($args);
		
		if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
		  $args = $args[0];
		}
		
		$query_tmp = strtolower($query);
		if(strrpos($query_tmp, ' limit ') == 0){
			$query .= ' LIMIT '. (int)$from .', '. (int)$count;
		}
		
		// get data
		$db=$this->getSlaveDB();
		$stm=$db->query($query, $args);
		
		$data=array();
		while ($obj=$stm->fetch())
		{
			$data[]=$obj;
		}
		return $data;
	}
	
	private function setPageInfo($pageInfo){
		$this->page_info = $pageInfo;
	}
	public function getPageInfo(){
		return $this->page_info;
	}
	
	public function pageQueryInfo($sql, $args, $isCountQuery=false){
		$info = array();
		$db=$this->getSlaveDB();
		
		
		if($isCountQuery){
			$countQuery = $sql;
		}
		else{
			$countQuery = preg_replace(array('/SELECT.*?FROM /As', '/ORDER BY .*/'), array('SELECT COUNT(*) FROM ', ''), $sql);
		}

		$stm=$db->query($countQuery, $args);

		$itemPerPage = $this->getItemPerPage();
		
		$info['total_item'] = $stm->fetchColumn();
		$info['total_page'] = ceil($info['total_item'] / $itemPerPage);
		return $info;
	}
	
	public static function makePageInfo($page, $limit, $count){
		$ret = array();
		$ret['page'] = $page;
		$ret['total_item'] =  $count;
		$limit = (int)$limit;
		if($limit){
			$ret['limit'] = $limit;
			$ret['total_page'] =  ceil($count / $limit);;
		}
		return $ret;
	}
	
	public function pageIndex($totalPage, $page=0){
		$info = array();
		$page = max(0, min((int)$page, ((int)$totalPage) - 1));
		$itemPerPage = $this->getItemPerPage();
		$info['start'] = $page*$itemPerPage;
		$info['limit'] = $itemPerPage;
		$info['page'] = $page;
		return $info;
	}
	
	public function getItemPerPage(){
		$itemPerPage = (int)$this->row_per_page;
		if(!$itemPerPage)
			$itemPerPage = 20;
		return $itemPerPage;
	}
	
	protected static function getCacheEngine()
	{
		if (self::$data_cache==null)
		{
			$reg=Zend_Registry::getInstance();
			$frontendOptions=array(
				'cache_id_prefix' => 'event_',
				'lifetime' => 1200,
				'automatic_serialization' => true
			);
			$backendOptions=$reg->memcached;
			self::$data_cache = Zend_Cache::factory('Core',	'Memcached', $frontendOptions, $backendOptions);
		}
		return self::$data_cache;
	}
	
	public function isCacheExist($key){
		$cache_eng=self::getCacheEngine();
		return $cache_eng->test($key);
	}
	
	
	protected function getCache($key)
	{
		if(isset($_GET['nocache']) && $_GET['nocache']==1)return false;
		$cache_eng=self::getCacheEngine();
		$time = time();
		$ttl = 300;
		
		$cache=false;
		if (!$cache = $cache_eng->load($key))
		{
			$this->cacheStats($key, "cache_miss");
			return false;
		}
		else
		{
			if (($time - $ttl) > ($cache->created + $cache->expire))
			{
				$cache->created = $time;			
				$cache_eng->save($cache, $key, array(), $ttl);
				$this->cacheStats($key, "cache_miss");
				return false;
			}
			$this->cacheStats($key, "cache_hit");
			return $cache->data;
		}
	}
	
	protected function setCache($key, $data, $timeout=1200)
	{
		$cache_eng=self::getCacheEngine();
		$time 			= time();
		$ttl 			= 300;	
		$cache 			= new stdClass;
		$cache->data 	= is_object($data) ? clone($data) : $data;
		$cache->created = $time;
		$cache->expire 	= $timeout;
		$cache_eng->save($cache, $key, array(), $timeout + $ttl);
		
		$this->cacheStats($key, "cache_set");
	}
	
	protected function deleteCache($key)
	{
		$cache_eng=self::getCacheEngine();
		$cache_eng->remove($key);
	}
	
	private function cacheStats($key, $status)
	{
		if ($GLOBALS['_DBG'])
		{
			$stats=Zend_Registry::get("cache_stats");
			$stats[$status][]=$key;
			Zend_Registry::set("cache_stats", $stats);
		}
	}
	
	public function makeIn($vids)
	{
		$in="";
		for ($i=0; $i<count($vids); $i++)
		{
			if ($in!="")
			{
				$in=$in . ", ";
			}
			$in=$in . (int)$vids[$i];
		}
		return "(" . $in . ")";
	}
	

}

